1. Field of the Invention
This invention is related to the fields of: COBOL Programming Language, Decimal Arithmetic, Decimal Numerics, and other closely related computer art.
2. Description of the Related Art
Computer programs (also software programs, or just programs) are instructions for a computer or computer system to perform a task. A computer system requires programs to function, typically executing the program's instructions with a central processor unit. A computer program has an executable form that the computer system uses directly to execute the instructions. The same program in its human-readable source code form, from which executable programs are derived (e.g., compiled), enables a programmer to describe a task for a computer to perform. Computer source code is typically written by professional computer programmers. Source code is typically written in a programming language that allows for a programmer to describe tasks or functions for a computer to perform in a form that is relatively independent of the particular computer on which the program is run. That is, computer programs are often written in a “high level” language with the description of the task called “source” or “source code”. The source code which describes a task is typically processed by a “compiler” (compiled) and an “executable program” is produced which can be executed (run) on a specific type of computer. Different compilers, or different compiler options can be used to produce an executable program for different types of computers, computer systems, or computer systems with various operating systems. Source code is converted by a compiler into an executable program, (typically contained in a file called an executable program file or a “binary” file) and later “executed” on the computer system by one or more central processing units. Alternatively, computer programs may be executed with the aid of an interpreter, or may be embedded directly into hardware or firmware for a specific computing machine.
Computers may also be programmed at a lower level known as “assembly” or “machine” level programming. Assembly or machine level programming is typically utilized when performance is very important or when low level tasks must be performed which are not directly supported by a high level programming language. Assembly language programming typically describes programming at a level or in a language in which the central processor unit instructions and usage of the hardware registers of the central processor unit are described directly.
One of the more common high level programming languages for business related computer programs or applications is called “COBOL” COBOL is one of the oldest programming languages. Its name is an acronym for COmmon Business-Oriented Language, defining its primary domain in business, finance, and administrative systems for companies and governments. The COBOL language includes as one of its features the capability for representation of numbers stored in memory in base ten. That is, the value of a number can be described in COBOL to be represented in computer system memory as a series of decimal digits, with further description providing for storage or location of a decimal point, scale factors, exponents and/or other attributes. Decimal numbers from 0-9 require at least four binary bits of storage, with values 0-9 typically representing decimal numbers from 0-9 respectively, and with the remaining six possible values of a four bit number being utilized for other purposes such as to represent a sign or a decimal point. Decimal numbers may also be stored as a string of characters with a character being contained in a “byte” which can vary in size with typical byte size being 8-bits, 9-bits, 6-bits or other sizes as might be defined for a particular computer system. Two 4-bit decimal digits can be “packed” into a single 8-bit byte, or decimal digits can be stored one character per byte which is “unpacked”. Decimal digits may also be represented as full textual characters such as ASCII characters, that is, the ASCII value for the character “0” would be recognized as a number with the value of a decimal zero, and an ASCII character “1” would be a decimal numeric one, and so on. There are many ways of coding text characters and decimal values well known in the art of computing or which could be defined by one skilled in the art of computer programming or computer hardware design.
In the field of business computing, the performance of a computer system in performing decimal arithmetic calculations is critical because decimal arithmetic calculations are typically repeated many, many times within a business application or business transaction. In business applications, decimal numbers are often described and stored as fixed point decimal numbers with a scale factor that allows for a given number of decimal digits after the decimal point, such as two or three or more. Performance in the processing of decimal numbers is important enough that some computer companies such as Honeywell Inc. have included hardware and machine instructions within the Central Processing Unit of some of their computers for directly processing decimal numbers, that is directly processing decimal numbers represented as “ASCII” strings rather than in a binary representation (such as two's complement). Central Processing Unit hardware instructions are provided to perform decimal numeric operations such as add, subtract, multiply, divide and comparison operations.
On other computer systems however, direct support for decimal arithmetic is not provided and decimal calculations are typically performed by decimal numeric subroutines, the decimal numeric subroutines typically contained in a library. Calls to the decimal numeric functions are generated by a compiler and included in the executable code.
Decimal numeric functions are then invoked during execution as either machine instructions or calls to the subroutine library in order to perform a needed decimal numeric computation.
Decimal arithmetic is also of interest in the emulation of computer hardware or computing machines such as hardware emulators, or virtual machines such as the well known Java Virtual machine.
The COBOL computer language supports description of decimal numbers in many ways such as, for example, floating point decimal, fixed point decimal, unsigned decimal, signed decimal, overpunched signed ASCII, leading sign, trailing sign and so on.
Typically, in the prior art, hardware instructions or decimal arithmetic subroutine libraries are provided with attribute “descriptors” which describe attributes to the hardware instructions or to the arithmetic subroutines of the manner in which a referenced operand is stored in memory, and these attributes are used in “fetching” the operands, performing the operation, and then in “storing” a result. In order to perform a decimal operation, typically, for each operand, a compiler is used to provide to the hardware or to the decimal subroutine library, a pointer to the decimal “string” and a description in some form of the attributes which describe how the decimal operand is represented within the memory. For example in order to perform the operation A=B+C three pointers and three attribute descriptors would be provided by the compiler, one for each of the three operands A, B, and C. The pointers describe where the decimal “string” is located in computer system memory, and the attributes describe how the contents of that memory for each operand are to be interpreted. The points and the attributes can be combined into a single machine word or series of characters and there are many ways of providing pointers and descriptors or attributes of data such as decimal data that have been devised, or could be devised by one skilled in the art of computer design or computer programming.
Performing a desired decimal operation such as an “add” (decimal numeric add) typically requires the executing unit (i.e. hardware or software or firmware) performing the operation to examine the attributes of the input operands, move or align the data into a form where an addition can be properly performed (for example, line up the decimal points), perform the operation such as addition (including compensation such as that necessary to allow for “carries” to propagate across all decimal digits) and then convert the answer into a form such that it can be properly stored as defined by the attributes of the output (or “result”) operand, which in this example is the “A” operand.
The shifting, alignment, compensation for carries, reordering of bytes for such things as little-endian/big-endian compensation and other similar operations all take time, and require examining the data and further typically require comparing attributes, such as the scale factor, of the two input operands, and sometimes the output operand to complete the operation. This comparison of attributes takes time whether the operation is executed by hardware, software, in-line code, or processing within a subroutine library. Further, there is a need for performance increase in performing decimal operations since many business transactions, especially those related to financial matters, require calculations in decimal form.
Indeed, there are standards committees and groups that have studied methods of performing Decimal Arithmetic and the choice of formats for describing Decimal data such as the IEEE Subcommittee 754R which has proposed and revised the IEEE 754-1985 and IEEE 854-1987 Standards for decimal arithmetic. (IEEE is the Institute of Electrical and Electronic Engineers)
A programmer and/or compiler writer and/or machine designer is thus motivated to look for ways to improve performance of mathematical operations between decimal numeric operands, especially as provided in the COBOL high-level computer programming language. It would therefore be an advantage to provide a method, system and/or apparatus for carrying out the compilation and execution of a computer program utilizing decimal numeric variables and for improving the speed of calculations involving operations between two or more decimal numeric variables.
It seems useful to consider some of the points discussed above in greater detail using illustrative examples of decimal numeric variables that are typically those computer program variables represented numbers in memory stored in a manner relating to base 10 arithmetic. Decimal numeric representation of numbers and decimal arithmetic using decimal numerics are especially important in the industries of banking and finance where accuracy is important and where calculations using numbers represented in other bases such as base two may provide somewhat different answers than calculations done totally in base ten. These differences are often related to rounding, and also to truncation of lower precision digits when results cannot be represented in the allocated area of storage.
For example, the decimal number computation of determining:
IF (0.1 plus 0.2 plus 0.2 equals precisely 0.5)
is not directly possible using base two arithmetic because the representation of the decimal numbers in base two is not precise, although it is straight-forward using base ten arithmetic.
To illustrate, consider the number:
“0.1” (decimal), which is “0.0001100110010011 . . . ” (base 2).
Note that the value of 1/10 (decimal) is a repeating fraction in binary which looks like: “0.000110011001100110011001100110011 . . . ” which illustrates that 1/10 (decimal) cannot be stored precisely as a binary fraction.
Similarly, “0.2” (decimal) is “0. 001100110011 . . . ” (binary),
and “0.5” (decimal) is “0.10000000000 . . . ” (binary).
Now consider an example of adding 0.1 plus 0.2 plus 0.2 decimal, with those numbers represented as binary fractions with 0 binary places of precision.
“0.000110011” +(binary)“0.001100110” +(binary)“0.001100110” =(binary)0.011111111”(binary)which is “almost” “the value of “0.1000” (binary) or “0.5” (decimal), but not quite. So the “IF” comparison above would give a “false” comparison result when with total precision it really should give a “true” result, because 1/10 plus 2/10 plus 2/10 really is exactly “0.5” (decimal) or 5/10.
Tools for conversion of numbers from fixed point decimal representation to fixed point binary representation that can be used to address these peculiarities are readily available with one such tool being found on the World Wide Web at: “http://www.easysurf.cc/cnver17.htm”.
It is well known that there are various formats and standards for the storage of decimal numbers in memory of a computer system. Variables may be defined as a string of decimal digits with each digit having a value from zero to nine in the same manner as people normally think of decimal numbers. The decimal numbers may include a scale factor which provides a description of where a decimal point occurs within the digits of the decimal number. An exponent might also be provided, with the exponent in base ten, base two, or other representation. The decimal number may also be signed, that is it may be a positive or negative number with the sign being stored as an extra “digit” or combined in some way with other digits to indicate a sign. Combining the sign with other digits is sometimes called “overpunched” sign representation, which is terminology going back to the days of punch cards for representing numbers and characters to a computer system.
These elements which describe precisely how a decimal number stored in memory is to be interpreted can be called “element alignment information”. That is, in general, they describe how the number is stored in memory and the information is used to determine how one decimal number must be aligned with another decimal number in order to perform arithmetic operations such as addition or subtraction. They also describe where and/or how to determine the sign of the decimal number, and where to find the decimal point.
Performing a simple addition of two decimal numbers requires that the numbers be aligned. For example, in order to calculated 1.25 plus 1.555, the decimal points of the two numbers must be aligned such as indicated below:
                                                1.25        ∼                        +                      1.555        _                        =              2.755      In memory these numbers might be represented as strings of digits with scale factors:
(125*10^−2)+(1555*10^−3)=>2755*10^−3
Performing these calculations require that the number “125” be aligned properly with the number “1555” so as to correctly perform the addition computation. This alignment requires comparing the scale factor of the first number with the scale factor of the second number so as to calculate a shifting of one operand or the other so as to align the implied decimal points of the two operands and then perform the addition computation. In this example the first numbers scale factor of “−2” is compared to the second numbers scale factor of “−3” with a difference value of “1” and the first number is shifted to the left one decimal digit before it is added to the second number. In this manner the computation might look like this:
                                        1250                      *                  10          ^                      -            3                                                        <<          <<<<                ⁢                                  ⁢                  (                      this            ⁢                                                  ⁢            number            ⁢                                                  ⁢            was            ⁢                                                  ⁢            shifted            ⁢                                                  ⁢            one            ⁢                                                  ⁢            to            ⁢                                                  ⁢            the            ⁢                                                  ⁢            left                                          +                      1555        _                            *                  10          ^                      -            3                                                                                        ⁢                                                ⁢                  before          ⁢                                          ⁢          the          ⁢                                          ⁢          addition          ⁢                                          ⁢          was          ⁢                                          ⁢          performed                )                        =              2755                      *                  10          ^                      -            3                                              …        ⁢                                  ⁢                  (                      which            ⁢                                                  ⁢            is            ⁢                                                  ⁢            2.755                    )                    
It is noted for this discussion that the term “scale factor” and “exponent” are two distinct terms. “Scale factor” defines or describes an alignment or shifting of a number where the amount of the alignment or shift is expressed as a constant. For example a string of digits “1234” with a scale factor of two would be considered to have a value of 12.34, and “1357” with a scale factor of one would be valued as a decimal 135.7. In order to add these numbers “1234” and “1357” would be aligned as below:
                                        01234                                              +                      13570        _                                                    =              14804                      which        ⁢                                  ⁢        has        ⁢                                  ⁢        a        ⁢                                  ⁢        scale        ⁢                                                  ⁢                                                ⁢        factor        ⁢                                  ⁢        of        ⁢                                  ⁢        two        ⁢                                                  ⁢                                                ⁢        giving        ⁢                                  ⁢        148.04            The “constant” shift means that the numbers stored in memory always have the decimal point in the same place. This is in contrast to an “exponent” where the numbers have an implied decimal point, but also have an exponent value which is a multiplier that can move the exponent right or left. In scientific notation, the number “48.04” would be expressed as (1.4804*10^2) that is, with an exponent of two and the implied decimal point always one to the right of the first digit. The “scale factor” for a number is constant and is not necessarily stored in memory relating to the number. In contrast, an “exponent” can vary in value, and therefore must be stored “with” or in memory relating to the number in order to determine its overall value completely (that is, including the multiplication by the exponent value). Numbers with equivalent scale factors can be added without shifting or alignment without knowledge of the actual value of the scale factor. For example, 12.34 can be added to 15.0 with a result of 27.35 without knowledge of the actual location of the decimal point. That is, 1234 is added to 1501 with an answer of 2735 and stored in that fashion in memory with only the programmer or the compiler program actually “knowing” the actual location of the decimal point.
These arithmetic calculations on decimal numerics are often performed by an execution unit that can be implemented by hardware, software or firmware that is tuned or optimized for performing these functions, that is, for example, the numeric operations may be performed by routines optimized for the purpose which are external to a main computer program. Decimal numerics are often implemented/provided in function subroutines libraries, or by special hardware instructions that are typically multi-word instructions that provide pointers to the operand arguments and description of those arguments as to their characteristics such as scale factor, and/or manner of sign storage.
A typical list of arguments provided to these optimized “subroutines” (or other similar manner of implementation such as a complex hardware function) for performing an add of two decimal numbers (e.g. A, B) is as follows:
a) a pointer to the data A, which is a pointer to a first “string” of decimal digits;
b) a pointer to the data B, which is a pointer to a second “string” of decimal digits;
c) an indication as to “scale factor” of Operand A;
d) an indication as to “scale factor” of Operand B;
e) an indication as to where or how the sign of the number is stored for Operand A;
f) an indication as to where or how the sign of the number is stored for Operand B; and,
g) similar information as to where/how to store the result of the addition.
When invoked, the library subroutine takes the scale factor of Operand A and compares it to the scale factor of Operand B, moves the digits of Operand A and Operand B into identical alignment and then performs the addition of the digits. The decimal addition may be performed multiple digits at a time, as in for example eight or sixteen digits within a 64-bit word that are added together, or the overall addition can be performed one digit at a time with carry propagation as required. Note that adding two decimal numbers which are represented as characters may require special addition of intermediate values to allow for carry propagation across the characters. This approach is well known in the art and is readily understood by one skilled in the art of arithmetic and digital systems logic design or computer programming.
Comparison of the scale factors may be needed even if the input operand data is not moved into a temporary storage location and also even if the digits are added one at a time because the fetching of the digits must provide in some way for alignment of the two numbers if the scale factors are different. The alignment requires preliminary computation steps in the comparison of the scale factors and may be followed by conditional processing steps dependent upon the results of the calculations. Alignment and computation of the result may also require consideration of the sign of the number. These processing steps take time and slow the performance in the computation of results.
The COBOL computer programming language provides for description (declaration) of decimal numerics in a plurality of memory storage formats. These formats include both fixed decimal and floating decimal point formats, in addition to declaration of binary (base two) integers. COBOL also provides for character strings which can be decimal numbers, as long as the digits of the character values are characters from “0” to “9”. The language of COBOL specifically provides for description of decimal numerics in a manner easily understood by people in that the calculations are performed in a manner so that the results are identical to what would be done if a person were to calculate the results by hand, that is, a “pencil and paper” method. This means that calculations are made in base ten with a reasonable limit on precision, that is, the number of digits to the right of the decimal point. With the COBOL language numbers of this type can be declared with “PICTURE” (or “PIC”) statements. Some typical declarations of variables in the COBOL language are as shown:
MAXPIC 99 VALUE 20 <constant>VAR4-1PIC S9999SVAR4-2PIC S9(4)VALUE1PIC S9(7)V99<“Implied” decimal point>VALUE2PIC S9(7)V99<“Implied” decimal point>VALUEAPIC S9(7) .99<“Real” decimal point>VALUEBPIC S9(7) .99<“Real” decimal point>TOTALITPIC S9(12)V99<“Result variable>
The COBOL programming language provides for both “REAL” and “IMPLIED” decimal points within the memory allocated for storing a decimal number. Most people tend to think of decimal numbers with a real decimal point included somewhere within the number and actually occupying a character position. That is “123.456” would be a seven character string in memory (without counting any “termination” character such as a null character, as in the “C” language). In COBOL however it is much more common and efficient to describe variables with an “IMPLIED” decimal point. That is, the compiler (and the programmer) knows where the decimal point is located, but the decimal point character is not actually stored in memory. “123.456” would be stored as “123456”, a six character string in memory.
Typically decimal numeric calculations are performed during the execution (run time) of a COBOL program by an executing unit such as a library function, or by invoking a specific “subroutine” which passes a list of arguments to a common piece of code which performs the actual decimal numeric computation. An argument list typically provides, to the subroutine, a description of each or the plurality of input operand and where to store the output result. Within the argument list, each input operand is characterized independently of the others, and the characteristics of the memory locations to be utilized for storing the result are also provided independently.